#include "Scene01.h"

Scene01::Scene01(Managers *managers)
{
	this ->managers = managers;

	currentCam = NULL;
}

Scene01::~Scene01(void)
{
	if (framebuffer != NULL)
		delete framebuffer;

	if (orTexture != NULL)
		delete orTexture;

	if (blur != NULL)
		delete blur;

	if (orDepthTexture != NULL)
		delete orDepthTexture;
}

void Scene01::Initialize()
{
	fadeMod = 0.0f;
	fade = 1.0f;

	futurisaFade = 0;
	futurisaFadeMod = 0;
	futurisbFade = 0;
	futurisbFadeMod = 0;
	dementiaaFade = 0;
	dementiaaFadeMod = 0;
	dementiabFade = 0;
	dementiabFadeMod = 0;
	asmcodeFade = 0;
	asmcodeFadeMod = 0;
	biterFade = 0;
	biterFadeMod = 0;
	lambFade = 0;
	lambFadeMod = 0;
	neveeFade = 0;
	neveeFadeMod = 0;

	ZeroMemory(idm, sizeof(float) * 16);
	idm[0] = 1.0f;
	idm[5] = 1.0f;
	idm[10] = 1.0f;
	idm[15] = 1.0f;

	vpSpecular = managers ->vertexShaderMan ->Get("specular");
	fpSpecular = managers ->pixelShaderMan ->Get("specular");
	vpDof = managers ->vertexShaderMan ->Get("dof");
	fpDof = managers ->pixelShaderMan ->Get("dof");
	vpBlur = managers ->vertexShaderMan ->Get("blur");
	fpBlur = managers ->pixelShaderMan ->Get("blur");

	cgpSpotLightPos = cgGetNamedParameter(fpSpecular ->GetProgram(), "spotLightPos");
	cgpSpotLightTargetPos = cgGetNamedParameter(fpSpecular ->GetProgram(), "spotLightTargetPos");
	modelMatrix = cgGetNamedParameter(vpSpecular ->GetProgram(), "modelMatrix");
	cgpFade = cgGetNamedParameter(fpDof ->GetProgram(), "fade");

	garden = managers ->modelMan ->Get("scene01");
	ground = new Ground(managers ->modelMan ->Get("loan"),managers ->texMan ->Get("grass"), managers);
	lamps = new MultiModel(managers ->modelMan ->Get("lamp"), "data\\3d\\lamp.pos", modelMatrix);
	windows = new MultiModel(managers ->modelMan ->Get("window"), "data\\3d\\windows.pos", modelMatrix);
	pales = new MultiModel(managers ->modelMan ->Get("pale"), "data\\3d\\pales.pos", modelMatrix);
	//trees = new MultiModel(managers ->modelMan ->Get("tree"), "data\\3d\\trees.pos", modelMatrix);
	skybox = managers ->modelMan ->Get("skybox");

	anim = managers ->animMan ->Get("scene01");

	scena1camera1 = managers ->camerasManager ->Get("scena1camera1");
	scena1camera5 = managers ->camerasManager ->Get("scena1camera5");
	scena1camera6 = managers ->camerasManager ->Get("scena1camera6");
	scena1camera02 = managers ->camerasManager ->Get("scena1camera02");
	scena1camera03 = managers ->camerasManager ->Get("scena1camera03");
	scena1camera04 = managers ->camerasManager ->Get("scena1camera04");
	
	framebuffer = new Framebuffer();
	framebuffer ->Initialize(1024, 1024, 32);

	orTexture = new Texture(1024, 1024, 32, NULL);
	orTexture ->BindTexture();
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	orDepthTexture = new DepthTexture(1024, 1024);

	blur = new Blur(framebuffer, 3, 1, vpBlur, fpBlur);

	currentCam = managers ->camerasManager ->Get("SteerCamera");

	cgGLSetParameter1f(cgpFade, 1.0f);

	SetAnimation();

	/*Mesh **meshes = garden ->GetMeshes();
	for (int i = 0; i < garden ->GetMeshCount(); i++)
		anim ->AttachAnimatable(meshes[i]);*/
}

void Scene01::Render(float ms)
{
	//currentCam = managers ->camerasManager ->Get("SteerCamera");

	fade += fadeMod * (ms / 1000.0f);
	fade = min(1.0f, max(fade, 0.0f));

	cgGLSetParameter1f(cgpFade, fade);

	if (currentCam == NULL)
		return;

	vpSpecular ->DoShader();
	fpSpecular ->DoShader();

	framebuffer ->AttachColorTexture(orTexture ->GetId());
	framebuffer ->AttachDepthTexture(orDepthTexture ->GetId());
	framebuffer ->StartRenderToTexture();
	glViewport(0, 0, 1024, 1024);

	anim ->Process(ms);
	anim ->ProcessAnimatables(ms);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	//glScalef(1.0f, 1.0f, 1.0f);

	currentCam ->Process(ms);
	currentCam ->SetViewMatrix();

	cgGLDisableProfile(CG_PROFILE_VP30);
	cgGLDisableProfile(CG_PROFILE_FP30);
	cgGLSetStateMatrixParameter(
		cgGetNamedParameter(vpDof ->GetProgram(), "modelViewProj"),
		CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);
	glEnable(GL_TEXTURE_2D);
	glDisable(GL_LIGHTING);
	glDepthMask(GL_FALSE);
	sm::Vec3 eyePos = currentCam ->GetPosition();
	glTranslatef(eyePos.x, eyePos.y, eyePos.z);
	//cgGLSetParameter1f(cgGetNamedParameter(fpSpecular ->GetProgram(), "focalDistance"), 99999.0f);
	skybox ->Render();
	glTranslatef(-eyePos.x, -eyePos.y, -eyePos.z);
	glDepthMask(GL_TRUE);

	cgGLSetStateMatrixParameter(
		cgGetNamedParameter(vpSpecular ->GetProgram(), "modelViewProj"),
		CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);

	vpSpecular ->DoShader();
	fpSpecular ->DoShader();

	cgGLSetParameter3f(cgGetNamedParameter(fpSpecular ->GetProgram(), "lightPosition"), 100, 1000, 100);	
	cgGLSetParameter3f(cgGetNamedParameter(fpSpecular ->GetProgram(), "eyePosition"), eyePos.x, eyePos.y, eyePos.z);
	cgGLSetParameter1f(cgGetNamedParameter(fpSpecular ->GetProgram(), "focalDistance"), currentCam ->GetTargetDistance());

	cgGLSetMatrixParameterfc(modelMatrix, idm);

	//anim ->Render();
	garden ->Render();
	ground ->Process(ms);
	ground ->Render();

	lamps ->Process(ms);
	lamps ->Render();
	windows ->Process(ms);
	windows ->Render();
	pales ->Render();
	//trees ->Render();

	framebuffer ->FinishRenderToTexture();

	blur ->MakeBlur(orTexture ->GetId());

	glDisable(GL_DEPTH_TEST);

	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	gluOrtho2D(0, 1280, 0, 1024);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glViewport(0, 0, 1280, 1024);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	vpDof ->DoShader();
	fpDof ->DoShader();

	cgGLSetStateMatrixParameter(
		cgGetNamedParameter(vpDof ->GetProgram(), "modelViewProj"),
		CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);

	cgGLSetTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex0"), orTexture ->GetId());
	cgGLEnableTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex0"));
	cgGLSetTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex1"), blur ->GetBlurredTexture(0));
	cgGLEnableTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex1"));
	cgGLSetTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex2"), blur ->GetBlurredTexture(1));
	cgGLEnableTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex2"));
	cgGLSetTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex3"), blur ->GetBlurredTexture(2));
	cgGLEnableTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex3"));

	glBegin(GL_QUADS);
	glTexCoord2f(0, 0); glVertex2f(0, 0);
	glTexCoord2f(1, 0); glVertex2f(1280, 0);
	glTexCoord2f(1, 1); glVertex2f(1280, 1024);
	glTexCoord2f(0, 1); glVertex2f(0, 1024);
	glEnd();

	cgGLDisableProfile(CG_PROFILE_VP30);
	cgGLDisableProfile(CG_PROFILE_FP30);

	futurisaFade += futurisaFadeMod * (ms / 1000.0f);
	futurisaFade = min(1.0f, max(futurisaFade, 0.0f));

	if (futurisaFade > 0)
	{
		glDisable(GL_LIGHTING);
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);

		managers ->texMan ->Get("futurisa") ->BindTexture();

		glColor4f(1, 1, 1, futurisaFade);
		glBegin(GL_QUADS);
		glTexCoord2f(0, 0); glVertex2f(0, 0);
		glTexCoord2f(1, 0); glVertex2f(1280, 0);
		glTexCoord2f(1, 1); glVertex2f(1280, 1024);
		glTexCoord2f(0, 1); glVertex2f(0, 1024);
		glEnd();
		glColor4f(1, 1, 1, 1);

		glDisable(GL_BLEND);
	}

	futurisbFade += futurisbFadeMod * (ms / 1000.0f);
	futurisbFade = min(1.0f, max(futurisbFade, 0.0f));

	if (futurisbFade > 0)
	{
		glDisable(GL_LIGHTING);
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);

		managers ->texMan ->Get("futurisb") ->BindTexture();

		glColor4f(1, 1, 1, futurisbFade);
		glBegin(GL_QUADS);
		glTexCoord2f(0, 0); glVertex2f(0, 0);
		glTexCoord2f(1, 0); glVertex2f(1280, 0);
		glTexCoord2f(1, 1); glVertex2f(1280, 1024);
		glTexCoord2f(0, 1); glVertex2f(0, 1024);
		glEnd();
		glColor4f(1, 1, 1, 1);

		glDisable(GL_BLEND);
	}

	dementiaaFade += dementiaaFadeMod * (ms / 1000.0f);
	dementiaaFade = min(1.0f, max(dementiaaFade, 0.0f));

	if (dementiaaFade > 0)
	{
		glDisable(GL_LIGHTING);
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);

		managers ->texMan ->Get("dementiaa") ->BindTexture();

		glColor4f(1, 1, 1, dementiaaFade);
		glBegin(GL_QUADS);
		glTexCoord2f(0, 0); glVertex2f(0, 0);
		glTexCoord2f(1, 0); glVertex2f(1280, 0);
		glTexCoord2f(1, 1); glVertex2f(1280, 1024);
		glTexCoord2f(0, 1); glVertex2f(0, 1024);
		glEnd();
		glColor4f(1, 1, 1, 1);

		glDisable(GL_BLEND);
	}

	dementiabFade += dementiabFadeMod * (ms / 1000.0f);
	dementiabFade = min(1.0f, max(dementiabFade, 0.0f));

	if (dementiabFade > 0)
	{
		glDisable(GL_LIGHTING);
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);

		managers ->texMan ->Get("dementiab") ->BindTexture();

		glColor4f(1, 1, 1, dementiabFade);
		glBegin(GL_QUADS);
		glTexCoord2f(0, 0); glVertex2f(0, 0);
		glTexCoord2f(1, 0); glVertex2f(1280, 0);
		glTexCoord2f(1, 1); glVertex2f(1280, 1024);
		glTexCoord2f(0, 1); glVertex2f(0, 1024);
		glEnd();
		glColor4f(1, 1, 1, 1);

		glDisable(GL_BLEND);
	}

	asmcodeFade += asmcodeFadeMod * (ms / 1000.0f);
	asmcodeFade = min(1.0f, max(asmcodeFade, 0.0f));

	if (asmcodeFade > 0)
	{
		glDisable(GL_LIGHTING);
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);

		managers ->texMan ->Get("asmcode") ->BindTexture();

		glColor4f(1, 1, 1, asmcodeFade);
		glBegin(GL_QUADS);
		glTexCoord2f(0, 0); glVertex2f(0, 0);
		glTexCoord2f(1, 0); glVertex2f(1280, 0);
		glTexCoord2f(1, 1); glVertex2f(1280, 1024);
		glTexCoord2f(0, 1); glVertex2f(0, 1024);
		glEnd();

		glDisable(GL_BLEND);
	}

	biterFade += biterFadeMod * (ms / 1000.0f);
	biterFade = min(1.0f, max(biterFade, 0.0f));

	if (biterFade > 0)
	{
		glDisable(GL_LIGHTING);
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);

		managers ->texMan ->Get("biter") ->BindTexture();

		glColor4f(1, 1, 1, biterFade);
		glBegin(GL_QUADS);
		glTexCoord2f(0, 0); glVertex2f(0, 0);
		glTexCoord2f(1, 0); glVertex2f(1280, 0);
		glTexCoord2f(1, 1); glVertex2f(1280, 1024);
		glTexCoord2f(0, 1); glVertex2f(0, 1024);
		glEnd();

		glDisable(GL_BLEND);
	}

	lambFade += lambFadeMod * (ms / 1000.0f);
	lambFade = min(1.0f, max(lambFade, 0.0f));

	if (lambFade > 0)
	{
		glDisable(GL_LIGHTING);
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);

		managers ->texMan ->Get("lamb") ->BindTexture();

		glColor4f(1, 1, 1, lambFade);
		glBegin(GL_QUADS);
		glTexCoord2f(0, 0); glVertex2f(0, 0);
		glTexCoord2f(1, 0); glVertex2f(1280, 0);
		glTexCoord2f(1, 1); glVertex2f(1280, 1024);
		glTexCoord2f(0, 1); glVertex2f(0, 1024);
		glEnd();

		glDisable(GL_BLEND);
	}

	neveeFade += neveeFadeMod * (ms / 1000.0f);
	neveeFade = min(1.0f, max(neveeFade, 0.0f));

	if (neveeFade > 0)
	{
		glDisable(GL_LIGHTING);
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);

		managers ->texMan ->Get("nevee") ->BindTexture();

		glColor4f(1, 1, 1, neveeFade);
		glBegin(GL_QUADS);
		glTexCoord2f(0, 0); glVertex2f(0, 0);
		glTexCoord2f(1, 0); glVertex2f(1280, 0);
		glTexCoord2f(1, 1); glVertex2f(1280, 1024);
		glTexCoord2f(0, 1); glVertex2f(0, 1024);
		glEnd();

		glDisable(GL_BLEND);
	}


	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);

	glEnable(GL_DEPTH_TEST);
}

void Scene01::Notify(float time, const char *type, const char *value)
{
	if (strcmp(type, "camera") == 0)
	{
		currentCam = managers ->camerasManager ->Get(value);
	}

	if (strcmp(type, "effect") == 0)
	{
		if (strcmp(value, "fadedown") == 0)
		{
			fadeMod = -1.0f;
		}

		if (strcmp(value, "fadeup") == 0)
		{
			fadeMod = 1.0f;
		}
	}

	if (strcmp(type, "spriteon") == 0)
	{
		if (strcmp(value, "futurisa") == 0)
			futurisaFadeMod = 1.0f;
		else if (strcmp(value, "futurisb") == 0)
			futurisbFadeMod = 1.0f;
		else if (strcmp(value, "dementiaa") == 0)
			dementiaaFadeMod = 1.0f;
		else if (strcmp(value, "dementiab") == 0)
			dementiabFadeMod = 1.0f;
		else if (strcmp(value, "asmcode") == 0)
			asmcodeFadeMod = 1.0f;
		else if (strcmp(value, "biter") == 0)
			biterFadeMod = 1.0f;
		else if (strcmp(value, "lamb") == 0)
			lambFadeMod = 1.0f;
		else if (strcmp(value, "nevee") == 0)
			neveeFadeMod = 1.0f;
	}

	if (strcmp(type, "spriteoff") == 0)
	{
		if (strcmp(value, "futurisa") == 0)
			futurisaFadeMod = -1.0f;
		else if (strcmp(value, "futurisb") == 0)
			futurisbFadeMod = -1.0f;
		else if (strcmp(value, "dementiaa") == 0)
			dementiaaFadeMod = -1.0f;
		else if (strcmp(value, "dementiab") == 0)
			dementiabFadeMod = -1.0f;
		else if (strcmp(value, "asmcode") == 0)
			asmcodeFadeMod = -1.0f;
		else if (strcmp(value, "biter") == 0)
			biterFadeMod = -1.0f;
		else if (strcmp(value, "lamb") == 0)
			lambFadeMod = -1.0f;
		else if (strcmp(value, "nevee") == 0)
			neveeFadeMod = -1.0f;
	}
}

void Scene01::SetLights()
{
	ZeroMemory(lights, sizeof(float) * 3 * 17);

	Light *light;
	sm::Vec3 lightPos;
	sm::Vec3 lightTargetPos;
	char name[1024];

	int lightIndex = 0;

	for (int i = 0; i < managers ->lightsManager ->GetCount(); i++)
	{
		managers ->lightsManager ->Get(i, name, light);

		if (strstr(name, "scena1") != NULL)
		{
			lightPos = light ->GetPosition();
			lightTargetPos = light ->GetTargetPosition();
			lights[(lightIndex * 3) + 0] = lightPos.x;
			lights[(lightIndex * 3) + 1] = lightPos.y;
			lights[(lightIndex * 3) + 2] = lightPos.z;
			lightsTargets[(lightIndex * 3) + 0] = lightTargetPos.x;
			lightsTargets[(lightIndex * 3) + 1] = lightTargetPos.y;
			lightsTargets[(lightIndex * 3) + 2] = lightTargetPos.z;

			lightIndex++;

			anim ->AttachAnimatable(light);
			anim ->AttachAnimatable(light ->GetTarget());
		}
	}

	cgGLSetParameterArray3f(cgpSpotLightPos, 0, 17, lights);	
	cgGLSetParameterArray3f(cgpSpotLightTargetPos, 0, 17, lightsTargets);
}

void Scene01::SetAnimation()
{
	anim ->AttachAnimatable(scena1camera1);
	anim ->AttachAnimatable(scena1camera1 ->GetTarget());
	anim ->AttachAnimatable(scena1camera5);
	anim ->AttachAnimatable(scena1camera5 ->GetTarget());
	anim ->AttachAnimatable(scena1camera6);
	anim ->AttachAnimatable(scena1camera6 ->GetTarget());
	anim ->AttachAnimatable(scena1camera02);
	anim ->AttachAnimatable(scena1camera02 ->GetTarget());
	anim ->AttachAnimatable(scena1camera03);
	anim ->AttachAnimatable(scena1camera03 ->GetTarget());
	anim ->AttachAnimatable(scena1camera04);
	anim ->AttachAnimatable(scena1camera04 ->GetTarget());
}

void Scene01::Prepare()
{
	SetLights();
}
